home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / sh03src.zoo / sh-pl03 / sh / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-23  |  7.1 KB  |  342 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Kenneth Almquist.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. char copyright[] =
  39. "@(#) Copyright (c) 1991 The Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif /* not lint */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@(#)main.c    5.2 (Berkeley) 3/13/91";
  45. #endif /* not lint */
  46.  
  47. #include <signal.h>
  48. #include <fcntl.h>
  49. #include "shell.h"
  50. #include "main.h"
  51. #include "mail.h"
  52. #include "options.h"
  53. #include "output.h"
  54. #include "parser.h"
  55. #include "nodes.h"
  56. #include "eval.h"
  57. #include "jobs.h"
  58. #include "input.h"
  59. #include "trap.h"
  60. #if ATTY
  61. #include "var.h"
  62. #endif
  63. #include "memalloc.h"
  64. #include "error.h"
  65. #include "init.h"
  66. #include "mystring.h"
  67.  
  68. #ifdef __MINT__
  69. long _stksize = 20*1024L;
  70. #endif
  71.  
  72. #define PROFILE 0
  73.  
  74. int rootpid;
  75. int rootshell;
  76. STATIC union node *curcmd;
  77. STATIC union node *prevcmd;
  78. extern int errno;
  79. #if PROFILE
  80. short profile_buf[16384];
  81. extern int etext();
  82. #endif
  83.  
  84. #ifdef __STDC__
  85. STATIC void read_profile(char *);
  86. char *getenv(char *);
  87. #else
  88. STATIC void read_profile();
  89. char *getenv();
  90. #endif
  91.  
  92.  
  93. /*
  94.  * Main routine.  We initialize things, parse the arguments, execute
  95.  * profiles if we're a login shell, and then call cmdloop to execute
  96.  * commands.  The setjmp call sets up the location to jump to when an
  97.  * exception occurs.  When an exception occurs the variable "state"
  98.  * is used to figure out how far we had gotten.
  99.  */
  100.  
  101. main(argc, argv)  char **argv; {
  102.     struct jmploc jmploc;
  103.     struct stackmark smark;
  104.     volatile int state;
  105.     char *shinit;
  106.  
  107. #if PROFILE
  108.     monitor(4, etext, profile_buf, sizeof profile_buf, 50);
  109. #endif
  110.     state = 0;
  111.     if (setjmp(jmploc.loc)) {
  112.         /*
  113.          * When a shell procedure is executed, we raise the
  114.          * exception EXSHELLPROC to clean up before executing
  115.          * the shell procedure.
  116.          */
  117.         if (exception == EXSHELLPROC) {
  118.             rootpid = getpid();
  119.             rootshell = 1;
  120.             minusc = NULL;
  121.             state = 3;
  122.         } else if (state == 0 || iflag == 0 || ! rootshell)
  123.             exitshell(2);
  124.         reset();
  125. #if ATTY
  126.         if (exception == EXINT
  127.          && (! attyset() || equal(termval(), "emacs"))) {
  128. #else
  129.         if (exception == EXINT) {
  130. #endif
  131.             out2c('\n');
  132.             flushout(&errout);
  133.         }
  134.         popstackmark(&smark);
  135.         FORCEINTON;                /* enable interrupts */
  136.         if (state == 1)
  137.             goto state1;
  138.         else if (state == 2)
  139.             goto state2;
  140.         else
  141.             goto state3;
  142.     }
  143.     handler = &jmploc;
  144. #ifdef DEBUG
  145.     opentrace();
  146.     trputs("Shell args:  ");  trargs(argv);
  147. #endif
  148.     rootpid = getpid();
  149.     rootshell = 1;
  150.     init();
  151.     setstackmark(&smark);
  152.     procargs(argc, argv);
  153. #ifdef __MINT__
  154.     /* under MiNT, we are also a login shell if we've been started
  155.      * from the desktop with no arguments
  156.      * hohmuth 22 Mar 1993
  157.      */
  158.     if (!argv[0] || (!argv[0][0] && !argv[1]))
  159.         argv[0] = "-sh";
  160. #endif
  161.     if (argv[0] && argv[0][0] == '-') {
  162.         state = 1;
  163.         read_profile("/etc/profile");
  164. state1:
  165.         state = 2;
  166. #ifdef DOSFS
  167.         read_profile("profile.sh");
  168. #else
  169.         read_profile(".profile");
  170. #endif
  171.     } else if ((sflag || minusc) && (shinit = getenv("SHINIT")) != NULL) {
  172.         state = 2;
  173.         evalstring(shinit);
  174.     }
  175. state2:
  176.     state = 3;
  177.     if (minusc) {
  178.         evalstring(minusc);
  179.     }
  180.     if (sflag || minusc == NULL) {
  181. state3:
  182.         cmdloop(1);
  183.     }
  184. #if PROFILE
  185.     monitor(0);
  186. #endif
  187.     exitshell(exitstatus);
  188. }
  189.  
  190.  
  191. /*
  192.  * Read and execute commands.  "Top" is nonzero for the top level command
  193.  * loop; it turns on prompting if the shell is interactive.
  194.  */
  195.  
  196. void
  197. cmdloop(top) {
  198.     union node *n;
  199.     struct stackmark smark;
  200.     int inter;
  201.     int numeof;
  202.  
  203.     TRACE(("cmdloop(%d) called\n", top));
  204.     setstackmark(&smark);
  205.     numeof = 0;
  206.     for (;;) {
  207.         if (pendingsigs)
  208.             dotrap();
  209.         inter = 0;
  210.         if (iflag && top) {
  211.             inter++;
  212.             showjobs(1);
  213.             chkmail(0);
  214.             flushout(&output);
  215.         }
  216.         n = parsecmd(inter);
  217. #ifdef DEBUG
  218.         /* showtree(n); */
  219. #endif
  220.         if (n == NEOF) {
  221.             if (Iflag == 0 || numeof >= 50)
  222.                 break;
  223.             out2str("\nUse \"exit\" to leave shell.\n");
  224.             numeof++;
  225.         } else if (n != NULL && nflag == 0) {
  226.             if (inter) {
  227.                 INTOFF;
  228.                 if (prevcmd)
  229.                     freefunc(prevcmd);
  230.                 prevcmd = curcmd;
  231.                 curcmd = copyfunc(n);
  232.                 INTON;
  233.             }
  234.             evaltree(n, 0);
  235. #ifdef notdef
  236.             if (exitstatus)                      /*DEBUG*/
  237.                 outfmt(&errout, "Exit status 0x%X\n", exitstatus);
  238. #endif
  239.         }
  240.         popstackmark(&smark);
  241.     }
  242.     popstackmark(&smark);        /* unnecessary */
  243. }
  244.  
  245.  
  246.  
  247. /*
  248.  * Read /etc/profile or .profile.  Return on error.
  249.  */
  250.  
  251. STATIC void
  252. read_profile(name)
  253.     char *name;
  254.     {
  255.     int fd;
  256.  
  257.     INTOFF;
  258.     if ((fd = open(name, O_RDONLY)) >= 0)
  259.         setinputfd(fd, 1);
  260.     INTON;
  261.     if (fd < 0)
  262.         return;
  263.     cmdloop(0);
  264.     popfile();
  265. }
  266.  
  267.  
  268.  
  269. /*
  270.  * Read a file containing shell functions.
  271.  */
  272.  
  273. void
  274. readcmdfile(name)
  275.     char *name;
  276.     {
  277.     int fd;
  278.  
  279.     INTOFF;
  280.     if ((fd = open(name, O_RDONLY)) >= 0)
  281.         setinputfd(fd, 1);
  282.     else
  283.         error("Can't open %s", name);
  284.     INTON;
  285.     cmdloop(0);
  286.     popfile();
  287. }
  288.  
  289.  
  290.  
  291. /*
  292.  * Take commands from a file.  To be compatable we should do a path
  293.  * search for the file, but a path search doesn't make any sense.
  294.  */
  295.  
  296. dotcmd(argc, argv)  char **argv; {
  297.     exitstatus = 0;
  298.     if (argc >= 2) {        /* That's what SVR2 does */
  299.         setinputfile(argv[1], 1);
  300.         commandname = argv[1];
  301.         cmdloop(0);
  302.         popfile();
  303.     }
  304.     return exitstatus;
  305. }
  306.  
  307.  
  308. exitcmd(argc, argv)  char **argv; {
  309.     if (argc > 1)
  310.         exitstatus = number(argv[1]);
  311.     exitshell(exitstatus);
  312. }
  313.  
  314.  
  315. lccmd(argc, argv)  char **argv; {
  316.     if (argc > 1) {
  317.         defun(argv[1], prevcmd);
  318.         return 0;
  319.     } else {
  320.         INTOFF;
  321.         freefunc(curcmd);
  322.         curcmd = prevcmd;
  323.         prevcmd = NULL;
  324.         INTON;
  325.         evaltree(curcmd, 0);
  326.         return exitstatus;
  327.     }
  328. }
  329.  
  330.  
  331.  
  332. #ifdef notdef
  333. /*
  334.  * Should never be called.
  335.  */
  336.  
  337. void
  338. exit(exitstatus) {
  339.     _exit(exitstatus);
  340. }
  341. #endif
  342.